/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.msu.client.discovery;

import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.msu.api.MsuService;
import io.iec.edp.caf.msu.api.client.ServiceDiscovery;
import io.iec.edp.caf.msu.api.entity.GspAppServerInstance;
import io.iec.edp.caf.msu.api.entity.GspSuInstance;
import io.iec.edp.caf.msu.api.entity.ServiceUnitInfo;
import io.iec.edp.caf.msu.api.server.MsuServiceDiscovery;
import io.iec.edp.caf.msu.client.exception.MsuNotFoundException;
import io.iec.edp.caf.msu.client.exception.ServiceUnitNotFoundException;
import io.iec.edp.caf.msu.common.domain.converter.GspSuConverter;
import io.iec.edp.caf.msu.common.domain.entity.GspSuEntity;
import io.iec.edp.caf.msu.common.domain.repository.SuRepository;
import io.iec.edp.caf.tenancy.api.context.MultiTenantContextInfo;
import io.iec.edp.caf.tenancy.core.context.MultiTenantContextHolder;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * DB部署 服务发现 返回一个健康的实例
 */
@Slf4j
public class DbDiscoveryImpl implements ServiceDiscovery {

    private SuRepository suRepo;

    public DbDiscoveryImpl(SuRepository suRepo) {
        this.suRepo = suRepo;
    }

    @Override
    public String discover(String serviceUnitName, HashMap<String, String> eventContext) {
        //结合GSPAppServerInstance和GSPSuInstance获取
        MsuService msuService = SpringBeanUtils.getBean(MsuService.class);
        List<GspAppServerInstance> appservers = msuService.getGspAppServerInfoBySu(serviceUnitName);

        //实例数量为0
        if (appservers.size() == 0) {
            log.error("ServiceCenter(DataBase) discover: Can't Found GspAppServerInstance by SU: " + serviceUnitName);
            throw new ServiceUnitNotFoundException("ServiceCenter(DataBase) discover: Current SU: " + serviceUnitName + " is not available");
        }

        //取第一个实例
        GspAppServerInstance instance = appservers.get(0);
        String url = instance.getAppUrl();

        if (url == null || url.length() == 0) {
            log.error("ServiceCenter(DataBase) discover: Can't Found GspAppServerInstance by SU: " + serviceUnitName);
            throw new ServiceUnitNotFoundException("ServiceCenter(DataBase) discover: Current SU: " + serviceUnitName + " is not available");
        }
        return url;
    }

    @Override
    public List<String> discoverAll(String serviceUnitName, HashMap<String, String> eventContext) {
        //todo
        return new ArrayList<>();
    }

    /**
     * 访问主库,获取GSPSuInstance表的所有数据并去重
     */
    @Override
    public List<ServiceUnitInfo> getEnabledServiceUnitInfo() {
        List<ServiceUnitInfo> infos = null;

        try {
            //设置主库
            MultiTenantContextInfo contextInfo = new MultiTenantContextInfo();
            contextInfo.setMasterDb(true);
            MultiTenantContextHolder.set(contextInfo);

            //读取GSPSuInstance
            List<GspSuEntity> allSuEntity = this.suRepo.findAll();
            if (allSuEntity.size() > 0) {
                infos = new ArrayList<>();
                for (GspSuEntity entity : allSuEntity) {
                    //去重加入
                    if (infos.stream().noneMatch(x -> x.getName().equals(entity.getSu()))) {
                        ServiceUnitInfo info = new ServiceUnitInfo();
                        info.setName(entity.getSu());
                        info.setServiceUnitDes(entity.getSu());
                        infos.add(info);
                    }
                }
            }
        } finally {
            MultiTenantContextHolder.set(null);
        }
        return infos;
    }

    @Override
    public String discover(String namespace, String serviceUnitName, HashMap<String, String> eventContext) {
        //系统间DB隔离，namespace天然隔离
        return discover(serviceUnitName, eventContext);
    }

    @Override
    public List<String> discoverAll(String namespace, String serviceUnitName, HashMap<String, String> eventContext) {
        //todo
        return new ArrayList<String>();
    }
}
